package com.study.base.io.nio.reactor;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by tan on 2017/7/14.
 */
public class Reactor implements Runnable {
	private Selector selector;
	private ServerSocketChannel serverSocket;

	public Reactor(int port) throws IOException {
		//创建服务端channel,并绑定端口，配置为非阻塞模式
		serverSocket = ServerSocketChannel.open();
		serverSocket.socket().bind(new InetSocketAddress(port));
		serverSocket.configureBlocking(false);
		//创建Selector对象，channel在selector上注册感兴趣的OP_ACCEPT事件
		selector = Selector.open();
		SelectionKey key = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
		key.attach(new Acceptor());
	}

	@Override
	public void run() {
		try {
			//单独一个线程，循环调用selector.select();来获取客户端链接事件。
			//循环调用肯定要有结束条件。结束条件:判断本线程是否被中断,如果被中断了,就结束循环。
			while (!Thread.interrupted()) {
				selector.select(10000);
				Set<SelectionKey> keySet = selector.selectedKeys();
				Iterator it = keySet.iterator();
				while (it.hasNext()) {
					//当key.isAcceptable()==true时，key是serverSocket的key
					//当key.isReadable()==true时，key是客户端的key
					dispatch((SelectionKey) it.next());
				}
				keySet.clear();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void dispatch(SelectionKey key) {

		Runnable r = (Runnable) (key.attachment());
		if (r != null) {
			r.run();
		}
	}

	class Acceptor implements Runnable {
		@Override
		public void run() {
			try {
				SocketChannel socket = serverSocket.accept();
				if (socket != null) {
					new Handler(selector, socket);
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
